/*  SSObjectFilterPanelController.m
 *  MESLib
 * 
 * Copyright 2003-2009 Starline Software Ltd
 * 
 * This file is part of MESLib.
 * 
 * MESLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MESLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with MESLib. If not, see <http://www.gnu.org/licenses/>.
 */
//  Created by Tobias Haughton on Wed Aug 20 2003.
//

#import "SSObjectFilterPanelController.h"
#import "SSCatalystDocument.h"

@implementation SSObjectFilterPanelController

+ (id)sharedObjectFilterPanelController {
   static SSObjectFilterPanelController *sharedObjectFilterPanelController = nil;

   if(!sharedObjectFilterPanelController) {
      sharedObjectFilterPanelController = [[SSObjectFilterPanelController allocWithZone:[self zone]] init];
   }
   
   return sharedObjectFilterPanelController;
}

- (id)init {
   self = [super initWithWindowNibName:@"ObjectFilterPanel"];
   if (self) {
      [self setWindowFrameAutosaveName:@"ObjectFilterPanel"];
   }
   return self;
}

- (void)setMainWindow:(NSWindow *)mainWindow {
   if([(SSCatalystDocument *)[[NSDocumentController sharedDocumentController] currentDocument] displayMode] != SSMatrixDisplayMode) {
      [self close];
   }
   
   needsUpdate = YES;
}

- (void)windowDidUpdate:(NSNotification *)notification {
   //this is called each time the window updates
   if(needsUpdate) {
      [self setRepresentedObject];
      needsUpdate = NO;

      [self setControlValues];
   }
}

- (void)windowWillClose:(NSNotification *)aNotification
{
   [[self window] makeFirstResponder:[self window]]; //this is so that controlTextDidEndEditing will be called if the user is still editing a text cell when they close the window
}

- (void)setControlValues
{
   if(representedObject) {
      [beginDateField setEnabled:YES];
      [endDateField setEnabled:YES];
      [beginTimeField setEnabled:YES];
      [endTimeField setEnabled:YES];
      [removeFiltersButton setEnabled:YES];

      if([representedObject filterWithIdentifier:[beginTimeField tag]]) {
         [beginDateField setObjectValue:[[representedObject filterWithIdentifier:[beginTimeField tag]] filterValue]];
         [beginTimeField setObjectValue:[[representedObject filterWithIdentifier:[beginTimeField tag]] filterValue]];
      } else {
         //no filter for this field
         [beginDateField setStringValue:[NSString string]];
         [beginTimeField setStringValue:[NSString string]];
      }

      if([representedObject filterWithIdentifier:[endTimeField tag]]) {
         [endDateField setObjectValue:[[representedObject filterWithIdentifier:[endTimeField tag]] filterValue]];
         [endTimeField setObjectValue:[[representedObject filterWithIdentifier:[endTimeField tag]] filterValue]];
      } else {
         //no filter for this field
         [endDateField setStringValue:[NSString string]];
         [endTimeField setStringValue:[NSString string]];
      }
   } else {
      //there is no document so disable the controls
      [beginDateField setEnabled:NO];
      [endTimeField setEnabled:NO];
      [beginDateField setEnabled:NO];
      [endTimeField setEnabled:NO];
      [removeFiltersButton setEnabled:NO];
   }
}

- (void)controlTextDidEndEditing:(NSNotification *)note
{
   //called when a text field stops editing

   if(representedObject) {
      switch([[note object] tag]) {
         case 0:
            [representedObject removeFilterWithIdentifier:[beginTimeField tag]]; //get rid of the old filter for this field
            if([[[note object] objectValue] isKindOfClass:[NSCalendarDate class]]) {
               [representedObject addFilterWithIdentifier:[beginTimeField tag]
                                                     type:SSStartsAfterDateFilterType
                                                    value:[self beginTimeFromFields]];
            } else {
               [beginDateField setObjectValue:[NSString string]];
               [beginTimeField setObjectValue:[NSString string]];
            }
               break;
         case 1:
            [representedObject removeFilterWithIdentifier:[endTimeField tag]]; //get rid of the old filter for this field
            if([[[note object] objectValue] isKindOfClass:[NSCalendarDate class]]) {
               [representedObject addFilterWithIdentifier:[endTimeField tag]
                                                     type:SSEndsBeforeDateFilterType
                                                    value:[self endTimeFromFields]];
            } else {
               [endDateField setObjectValue:[NSString string]];
               [endTimeField setObjectValue:[NSString string]];
            }
               break;
         default:
            break;
      }

      [[[NSDocumentController sharedDocumentController] currentDocument] updateObjectVisibility];
   }
}


- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string
errorDescription:(NSString *)error
{
   if([control isEqualTo:beginTimeField] || [control isEqualTo:endTimeField]) {
      //dealing with time
      //break the string into it's time segments
      NSArray *timeArray = [string componentsSeparatedByString:@":"];
      NSString *timeString = [NSString string];
      int i = 0;

      while(i < [timeArray count] && i < 4) {
         //include the < 4 incase the user has entered too many values
         timeString = [timeString stringByAppendingString:[timeArray objectAtIndex:i]]; //add the time value to the string

         if(i < 3) {
            //add the seperator
            timeString = [timeString stringByAppendingString:@":"];
         }

         i++;
      }

      while(i < 4) {
         //we have used all of the user entered values so pad with 0
         timeString = [timeString stringByAppendingString:@"0"];

         if(i < 3) {
            //add the seperator
            timeString = [timeString stringByAppendingString:@":"];
         }

         i++;
      }

      SSChartDate *cd = [[[SSChartDate alloc] initWithString:timeString calendarFormat:@"%H:%M:%S:%F"] autorelease];

      if(cd) {
         //the new date is valid so set the fields value to that
         [control setObjectValue:cd];
      } else {
         //the user entered un usable info so set the date to now
         [control setObjectValue:[SSChartDate calendarDate]];
      }

   } else if([control isEqualTo:beginDateField] || [control isEqualTo:endDateField]) {
      //it's a date so add today
      [control setObjectValue:[SSChartDate calendarDate]];
   }


   return NO;
}

- (IBAction)displayAll:(id)sender
{
   //remove the filters
   [representedObject removeFilterWithIdentifier:[beginTimeField tag]];
   [representedObject removeFilterWithIdentifier:[endTimeField tag]];

   //set the field values to nothing
   [beginDateField setStringValue:[NSString string]];
   [endDateField setStringValue:[NSString string]];
   [beginTimeField setStringValue:[NSString string]];
   [endTimeField setStringValue:[NSString string]];

   [[[NSDocumentController sharedDocumentController] currentDocument] updateObjectVisibility];
}

- (void)setRepresentedObject
{
   id currentDocument = [[NSDocumentController sharedDocumentController] currentDocument];
   if(currentDocument && [currentDocument respondsToSelector:@selector(objectFilterController)]) {
      representedObject = [(SSCatalystDocument *)[[NSDocumentController sharedDocumentController] currentDocument] objectFilterController];
   } else {
      representedObject = nil;
   }
}

- (NSCalendarDate *)beginTimeFromFields
{
   NSCalendarDate *finalDate;
   NSCalendarDate *dateObject = [beginDateField objectValue];
   NSCalendarDate *timeObject = [beginTimeField objectValue];

   if([dateObject isKindOfClass:[NSCalendarDate class]] && [timeObject isKindOfClass:[NSCalendarDate class]]) {
      //ther is a begin date and time so joing them into the same date
      finalDate = [[[NSCalendarDate alloc] initWithString:[NSString stringWithFormat:@"%@/%@/%@/%@/%@/%@/%@", [dateObject descriptionWithCalendarFormat:@"%Y"],
         [dateObject descriptionWithCalendarFormat:@"%m"], [dateObject descriptionWithCalendarFormat:@"%d"], [timeObject descriptionWithCalendarFormat:@"%H"],
         [timeObject descriptionWithCalendarFormat:@"%M"], [timeObject descriptionWithCalendarFormat:@"%S"], [timeObject descriptionWithCalendarFormat:@"%F"]]
                                        calendarFormat:@"%Y/%m/%d/%H/%M/%S/%F"] autorelease];
   } else {
      if(dateObject) {
         //there is a begin date but no time
         finalDate = dateObject;
         [beginTimeField setObjectValue:dateObject];
      } else {
         if(timeObject) {
            //there is a time but no date
            finalDate = timeObject;
            [beginDateField setObjectValue:timeObject];
         } else {
            //there is no time or date
            finalDate = [NSCalendarDate calendarDate];
            [beginDateField setObjectValue:finalDate];
            [beginTimeField setObjectValue:finalDate];
         }
      }
   }

   return finalDate;
}

- (NSCalendarDate *)endTimeFromFields
{
   NSCalendarDate *finalDate;
   NSCalendarDate *dateObject = [endDateField objectValue];
   NSCalendarDate *timeObject = [endTimeField objectValue];

   if([dateObject isKindOfClass:[NSCalendarDate class]] && [timeObject isKindOfClass:[NSCalendarDate class]]) {
      //ther is a end date and time so joing them into the same date
      finalDate = [[[NSCalendarDate alloc] initWithString:[NSString stringWithFormat:@"%@/%@/%@/%@/%@/%@/%@", [dateObject descriptionWithCalendarFormat:@"%Y"],
         [dateObject descriptionWithCalendarFormat:@"%m"], [dateObject descriptionWithCalendarFormat:@"%d"], [timeObject descriptionWithCalendarFormat:@"%H"],
         [timeObject descriptionWithCalendarFormat:@"%M"], [timeObject descriptionWithCalendarFormat:@"%S"], [timeObject descriptionWithCalendarFormat:@"%F"]]
                                        calendarFormat:@"%Y/%m/%d/%H/%M/%S/%F"] autorelease];
   } else {
      if(dateObject) {
         //there is a end date but no time
         finalDate = dateObject;
         [endTimeField setObjectValue:dateObject];
      } else {
         if(timeObject) {
            //there is a time but no date
            finalDate = timeObject;
            [endDateField setObjectValue:timeObject];
         } else {
            //there is no time or date
            finalDate = [NSCalendarDate calendarDate];
            [endDateField setObjectValue:finalDate];
            [endTimeField setObjectValue:finalDate];
         }
      }
   }

   return finalDate;
}

//*************************
- (BOOL)receiveClickedDateInfo
{
   //test to see if one of our date fields is being editied
   if([beginDateField currentEditor] || [beginTimeField currentEditor] ||
      [endDateField currentEditor] || [endTimeField currentEditor]) {
      return YES;
   }

   return NO;
}

- (void)userClickedDate:(SSChartDate *)date
{
   if([beginDateField currentEditor] || [beginTimeField currentEditor]) {
      // begin time is being edited insert date
      [beginDateField setObjectValue:date];
      [beginTimeField setObjectValue:date];

      //end editing so that the new value is set
      if([beginDateField currentEditor]) {
         [[beginDateField cell] endEditing:[beginDateField currentEditor]];
      } else {
         [[beginTimeField cell] endEditing:[beginTimeField currentEditor]];
      }
   } else if([endDateField currentEditor] || [endTimeField currentEditor]) {
      //end time is being edited
      [endDateField setObjectValue:date];
      [endTimeField setObjectValue:date];

      //end editing so that the new value is set
      if([endDateField currentEditor]) {
         [[endDateField cell] endEditing:[endDateField currentEditor]];
      } else {
         [[endTimeField cell] endEditing:[endTimeField currentEditor]];
      }
   }
}

@end
